class SyncParallelHook {
  constructor () {
    this.tasks = []
  }

  tap (name, task) {
    this.tasks.push(task)
  }

  tapAsync (name, task) {
    this.tasks.push(task)
  }

  callAsync (...args) {
    const finalCallback = args.pop()
    let index = 0
    const done = () => {
      index++
      if (index === this.tasks.length) {
        finalCallback()
      }
    }

    this.tasks.forEach(task => {
      task(...args, done)
    })
  }

  tapPromise (name, task) {
    this.tasks.push(task)
  }

  promise (...args) {
    const tasks = this.tasks.map(task => task(...args))

    return Promise.all(tasks)
  }
}

let hook = new SyncParallelHook(['name'])

hook.tapAsync('react', (name, cb) => {
  setTimeout(() => {
    console.log('react', name)
    cb()
  }, 1000)
})

hook.tapAsync('node', (name, cb) => {
  setTimeout(() => {
    console.log('node', name)
    cb()
  }, 1000)
})

hook.callAsync('xyf', () => {
  console.log('end')
})


let hook2 = new SyncParallelHook(['name promise'])

hook2.tapPromise('react', (name) => {
  return new Promise(((resolve, reject) => {
    setTimeout(() => {
      console.log('promise: react', name)
      resolve()
    }, 1000)
  }))
})

hook2.tapPromise('node', (name, cb) => {
  return new Promise(((resolve, reject) => {
    setTimeout(() => {
      console.log('promise: node', name)
      resolve()
    }, 1000)
  }))
})

hook2.promise('xyf').then(() => {
  console.log('promise: end')
})
